/**
 * GitCode API 服务层
 * 
 * 封装 GitCode API 调用，支持流式响应和多模态（图片分析）
 * Requirements: 1.1, 6.1
 */

import type { ApiChatMessage, ApiConfig, ContentPart } from '../types';

/**
 * 默认 API 配置
 * GitCode API v5
 */
const DEFAULT_CONFIG: ApiConfig = {
  apiUrl: 'https://api.gitcode.com/api/v5/chat/completions',
  apiKey: '',
  model: 'Qwen/Qwen3-VL-30B-A3B-Instruct',
  maxTokens: 1024,
  temperature: 0.7,
};

/**
 * API 响应中的 choice 结构
 */
interface ApiChoice {
  index: number;
  message?: {
    role: string;
    content: string;
  };
  delta?: {
    role?: string;
    content?: string;
  };
  finish_reason: string | null;
}

/**
 * API 响应结构
 */
interface ApiResponseBody {
  id: string;
  object: string;
  created: number;
  model: string;
  choices: ApiChoice[];
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

/**
 * API 错误类型
 */
export class GitCodeApiError extends Error {
  constructor(
    message: string,
    public readonly code: string,
    public readonly statusCode?: number
  ) {
    super(message);
    this.name = 'GitCodeApiError';
  }
}

/**
 * GitCode API 服务类
 * 
 * 提供与 GitCode API 交互的方法，包括：
 * - 普通聊天请求
 * - 流式聊天请求
 * - 图片分析（多模态）
 */
export class GitCodeApiService {
  private config: ApiConfig;

  constructor(config: Partial<ApiConfig> = {}) {
    this.config = { ...DEFAULT_CONFIG, ...config };
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<ApiConfig>): void {
    this.config = { ...this.config, ...config };
  }

  /**
   * 获取当前配置
   */
  getConfig(): ApiConfig {
    return { ...this.config };
  }

  /**
   * 构建请求体
   */
  buildRequestBody(messages: ApiChatMessage[], stream: boolean = false): object {
    return {
      model: this.config.model,
      messages: messages.map(msg => ({
        role: msg.role,
        content: msg.content,
      })),
      max_tokens: this.config.maxTokens,
      temperature: this.config.temperature,
      stream,
    };
  }

  /**
   * 构建请求头
   */
  buildHeaders(): Record<string, string> {
    return {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${this.config.apiKey}`,
    };
  }

  /**
   * 普通聊天请求（非流式）
   * 
   * @param messages - 聊天消息列表
   * @returns 生成的回复文本
   * @throws GitCodeApiError 当 API 调用失败时
   */
  async chat(messages: ApiChatMessage[]): Promise<string> {
    if (!this.config.apiKey) {
      throw new GitCodeApiError('API 密钥未配置', 'API_KEY_MISSING');
    }

    const requestBody = this.buildRequestBody(messages, false);
    
    try {
      const response = await fetch(this.config.apiUrl, {
        method: 'POST',
        headers: this.buildHeaders(),
        body: JSON.stringify(requestBody),
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new GitCodeApiError(
          `API 请求失败: ${errorText}`,
          'API_REQUEST_FAILED',
          response.status
        );
      }

      const data: ApiResponseBody = await response.json();
      
      if (!data.choices || data.choices.length === 0) {
        throw new GitCodeApiError('API 返回空响应', 'EMPTY_RESPONSE');
      }

      const content = data.choices[0].message?.content;
      if (content === undefined || content === null) {
        throw new GitCodeApiError('API 返回内容为空', 'EMPTY_CONTENT');
      }

      return content;
    } catch (error) {
      if (error instanceof GitCodeApiError) {
        throw error;
      }
      
      if (error instanceof TypeError && error.message.includes('fetch')) {
        throw new GitCodeApiError('网络连接失败', 'NETWORK_ERROR');
      }
      
      throw new GitCodeApiError(
        `未知错误: ${error instanceof Error ? error.message : String(error)}`,
        'UNKNOWN_ERROR'
      );
    }
  }

  /**
   * 流式聊天请求
   * 
   * @param messages - 聊天消息列表
   * @param onChunk - 接收每个文本块的回调函数
   * @returns 完整的生成文本
   * @throws GitCodeApiError 当 API 调用失败时
   */
  async chatStream(
    messages: ApiChatMessage[],
    onChunk: (text: string) => void
  ): Promise<string> {
    if (!this.config.apiKey) {
      throw new GitCodeApiError('API 密钥未配置', 'API_KEY_MISSING');
    }

    const requestBody = this.buildRequestBody(messages, true);
    
    try {
      const response = await fetch(this.config.apiUrl, {
        method: 'POST',
        headers: this.buildHeaders(),
        body: JSON.stringify(requestBody),
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new GitCodeApiError(
          `API 请求失败: ${errorText}`,
          'API_REQUEST_FAILED',
          response.status
        );
      }

      if (!response.body) {
        throw new GitCodeApiError('响应体为空', 'EMPTY_RESPONSE_BODY');
      }

      const reader = response.body.getReader();
      const decoder = new TextDecoder('utf-8');
      let fullContent = '';
      let buffer = '';

      while (true) {
        const { done, value } = await reader.read();
        
        if (done) {
          break;
        }

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        
        // 保留最后一个可能不完整的行
        buffer = lines.pop() || '';

        for (const line of lines) {
          const trimmedLine = line.trim();
          
          if (!trimmedLine || trimmedLine === 'data: [DONE]') {
            continue;
          }

          if (trimmedLine.startsWith('data: ')) {
            try {
              const jsonStr = trimmedLine.slice(6);
              const data: ApiResponseBody = JSON.parse(jsonStr);
              
              if (data.choices && data.choices.length > 0) {
                const delta = data.choices[0].delta;
                if (delta?.content) {
                  fullContent += delta.content;
                  onChunk(delta.content);
                }
              }
            } catch {
              // 忽略解析错误，继续处理下一行
            }
          }
        }
      }

      return fullContent;
    } catch (error) {
      if (error instanceof GitCodeApiError) {
        throw error;
      }
      
      if (error instanceof TypeError && error.message.includes('fetch')) {
        throw new GitCodeApiError('网络连接失败', 'NETWORK_ERROR');
      }
      
      throw new GitCodeApiError(
        `流式请求错误: ${error instanceof Error ? error.message : String(error)}`,
        'STREAM_ERROR'
      );
    }
  }

  /**
   * 图片分析（多模态）
   * 
   * 将图片转换为 Base64 格式并发送给 API 进行分析
   * 
   * @param imageBase64 - Base64 编码的图片数据（不含 data:image/xxx;base64, 前缀）
   * @param prompt - 分析提示词
   * @param mimeType - 图片 MIME 类型，默认为 image/png
   * @returns 分析结果文本
   * @throws GitCodeApiError 当 API 调用失败时
   */
  async analyzeImage(
    imageBase64: string,
    prompt: string,
    mimeType: string = 'image/png'
  ): Promise<string> {
    if (!this.config.apiKey) {
      throw new GitCodeApiError('API 密钥未配置', 'API_KEY_MISSING');
    }

    // 构建多模态消息内容
    const imageUrl = `data:${mimeType};base64,${imageBase64}`;
    
    const content: ContentPart[] = [
      {
        type: 'text',
        text: prompt,
      },
      {
        type: 'image_url',
        image_url: { url: imageUrl },
      },
    ];

    const messages: ApiChatMessage[] = [
      {
        role: 'user',
        content,
      },
    ];

    return this.chat(messages);
  }

  /**
   * 将 File 对象转换为 Base64 字符串
   * 
   * @param file - 图片文件
   * @returns Base64 编码的图片数据（不含前缀）
   */
  static async fileToBase64(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      
      reader.onload = () => {
        const result = reader.result as string;
        // 移除 data:image/xxx;base64, 前缀
        const base64 = result.split(',')[1];
        resolve(base64);
      };
      
      reader.onerror = () => {
        reject(new GitCodeApiError('文件读取失败', 'FILE_READ_ERROR'));
      };
      
      reader.readAsDataURL(file);
    });
  }

  /**
   * 获取文件的 MIME 类型
   * 
   * @param file - 文件对象
   * @returns MIME 类型字符串
   */
  static getMimeType(file: File): string {
    return file.type || 'image/png';
  }

  /**
   * 验证图片文件
   * 
   * @param file - 文件对象
   * @returns 验证结果
   */
  static validateImageFile(file: File): { valid: boolean; error?: string } {
    const validTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'];
    const maxSize = 10 * 1024 * 1024; // 10MB

    if (!validTypes.includes(file.type)) {
      return {
        valid: false,
        error: `不支持的图片格式: ${file.type}，支持的格式: PNG, JPEG, GIF, WebP`,
      };
    }

    if (file.size > maxSize) {
      return {
        valid: false,
        error: `图片文件过大: ${(file.size / 1024 / 1024).toFixed(2)}MB，最大支持 10MB`,
      };
    }

    return { valid: true };
  }
}

/**
 * 创建默认的 API 服务实例
 */
export function createApiService(apiKey: string): GitCodeApiService {
  return new GitCodeApiService({ apiKey });
}

/**
 * 导出默认实例（需要在使用前配置 API 密钥）
 */
export const defaultApiService = new GitCodeApiService();
